/*
 * Copyright (c) 2022 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include <stdio.h>
#include <unistd.h>
#include "ohos_types.h"
#include "ohos_init.h"
#include "hilog/log.h"
#include "thread_adapter.h"
#include "time_adapter.h"
#include "iunknown.h"
#include "service.h"
#include "samgr_lite.h"

#include "ohos_init.h"
#include "ohos_types.h"
#//include "utils_log.h"

#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <curl/curl.h>
#include <MQTTAsync.h>
#include <cJSON.h>
#include <stdbool.h> // 添加这个头文件以使用 bool 类型
#include <stdarg.h> // 对于C程序

#include "mqtt_ota.h"

/**********************************************************************************/
#define SEND_TOPIC "v1/platform/me/rpc/ota"
#define RECV_TOPIC "v1/devices/me/rpc/ota"

//#define RPC_REQUEST_PREFIX BASE_TOPIC "rpc/request/"

static char *deviceJSON = "{\"deviceInfo\":{\"name\":\"D1062140731725D001\",\"type\":\"\",\"provisionDeviceKey\":\"8bzljm4kom79simkhi2r\",\"provisionDeviceSecret\":\"t52ecibg3dreseqaieco\",\"isIPC\":0,\"isGateway\":1},\"otaInfo\":{\"firmwareFilePath\":\"/PowerHarmony/SMC/download/\",\"upgradeFileName\":\"/PowerHarmony/SMC/script/upgrade.sh\",\"rebootFileName\":\"/PowerHarmony/SMC/script/notifyReboot.sh\",\"statusFileName\":\"/PowerHarmony/SMC/download/upgradeStatus.ini\",\"recordFileName\":\"/PowerHarmony/SMC/download/record.json\"},\"logInfo\":{\"logFile\":\"\",\"logFileMaxSize\":5242880,\"logLevel\":3}}";

static char *getFirmwareInfoJSON = "{\"msgType\":2,\"msgTypeName\":\"checkNewVersion\",\"deviceInfo\":{\"name\":\"D1062140731725D001\",\"type\":\"\",\"provisionDeviceKey\":\"8bzljm4kom79simkhi2r\",\"provisionDeviceSecret\":\"t52ecibg3dreseqaieco\",\"isIPC\":0,\"isGateway\":1}}";

static char *firmwarePkgUrl = "http://10.50.80.72:5000/ota/updater.zip";
//static char g_configFileName[128]= "./conf/mqttInfo.json";

//  直连设备或者网关设备
typedef struct DEVICE_INFO
{
    char name[64];
    char type[32];
    char isGateway; 
    char isIPC; 
    char provisionDeviceKey[64];
    char provisionDeviceSecret[64];       

    char firmwareFilePath[128];
    char upgradeFileName[128];
    char rebootFileName[128];
    char statusFileName[128];
    char recordFileName[128];

    char logFile[64];
    unsigned int logFileMaxSize;
    char logLevel;
}DEVICE_INFO;
DEVICE_INFO   deviceInfo={0};

typedef struct ph_mqttInfo
{
    char ip[64];
    int  mqttPort;
    int  httpPort;
    char userName[64];
    char passwd[64];
    char certFile[64];
    char qos;
}ph_mqttInfo;

ph_mqttInfo *g_pMqttInfo = NULL;


/**********************************************************************************/

int getDeviceInfo(DEVICE_INFO * pDeviceInfo)
{
    cJSON * root = NULL;
    HILOG_INFO( LOG_CORE,"DEVICE_INFO start with mqttJSON \n%s",deviceJSON);
    root = cJSON_Parse(deviceJSON);

    if(root == NULL) return -1;
    
    int ret = 0;
    do{
        cJSON * json = NULL;
        cJSON * temp = NULL;
        if((json = cJSON_GetObjectItemCaseSensitive(root,"deviceInfo")) != NULL){          
            if((temp = cJSON_GetObjectItemCaseSensitive(json,"name")) != NULL){
                strncpy(pDeviceInfo->name,cJSON_GetStringValue(temp),sizeof(pDeviceInfo->name));
                pDeviceInfo->name[sizeof(pDeviceInfo->name)-1]='\0';
            }else{
                HILOG_INFO(LOG_CORE,"upgrade error");
                ret = -1;
                break;                
            }
            if((temp = cJSON_GetObjectItemCaseSensitive(json,"type")) != NULL){
                strncpy(pDeviceInfo->type,cJSON_GetStringValue(temp),sizeof(pDeviceInfo->type));
                pDeviceInfo->type[sizeof(pDeviceInfo->type)-1]='\0';
            }else{
                HILOG_INFO(LOG_CORE,"upgrade error");
                ret = -1;
                break;
            }
            if((temp = cJSON_GetObjectItemCaseSensitive(json,"provisionDeviceKey")) != NULL){
                strncpy(pDeviceInfo->provisionDeviceKey,cJSON_GetStringValue(temp),sizeof(pDeviceInfo->provisionDeviceKey));
                pDeviceInfo->provisionDeviceKey[sizeof(pDeviceInfo->provisionDeviceKey)-1]='\0';
            }else{
                HILOG_INFO(LOG_CORE,"upgrade error");
                ret = -1;
                break;                
            }
            if((temp = cJSON_GetObjectItemCaseSensitive(json,"provisionDeviceSecret")) != NULL){
                strncpy(pDeviceInfo->provisionDeviceSecret,cJSON_GetStringValue(temp),sizeof(pDeviceInfo->provisionDeviceSecret));
                pDeviceInfo->provisionDeviceSecret[sizeof(pDeviceInfo->provisionDeviceSecret)-1]='\0';
            }else{
                HILOG_INFO(LOG_CORE,"upgrade error");
                ret = -1;
                break;                
            } 
            if((temp = cJSON_GetObjectItemCaseSensitive(json,"isIPC")) != NULL){
                pDeviceInfo->isIPC = cJSON_GetNumberValue(temp);
            } 
            if((temp = cJSON_GetObjectItemCaseSensitive(json,"isGateway")) != NULL){
                pDeviceInfo->isGateway = cJSON_GetNumberValue(temp);
            }                                                            
        }
        if((json = cJSON_GetObjectItemCaseSensitive(root,"otaInfo")) != NULL){

            if((temp = cJSON_GetObjectItemCaseSensitive(json,"upgradeFileName")) != NULL){
                strncpy(pDeviceInfo->upgradeFileName,cJSON_GetStringValue(temp),sizeof(pDeviceInfo->upgradeFileName));
                pDeviceInfo->upgradeFileName[sizeof(pDeviceInfo->upgradeFileName)-1]='\0';
            }else{
                HILOG_INFO(LOG_CORE,"upgrade error");
                ret = -1;
                break;                
            }
            if((temp = cJSON_GetObjectItemCaseSensitive(json,"rebootFileName")) != NULL){
                strncpy(pDeviceInfo->rebootFileName,cJSON_GetStringValue(temp),sizeof(pDeviceInfo->rebootFileName));
                pDeviceInfo->rebootFileName[sizeof(pDeviceInfo->rebootFileName)-1]='\0';
            }else{
                HILOG_INFO(LOG_CORE,"upgrade error");
                ret = -1;
                break;                
            }
            if((temp = cJSON_GetObjectItemCaseSensitive(json,"firmwareFilePath")) != NULL){
                strncpy(pDeviceInfo->firmwareFilePath,cJSON_GetStringValue(temp),sizeof(pDeviceInfo->firmwareFilePath));
                pDeviceInfo->firmwareFilePath[sizeof(pDeviceInfo->firmwareFilePath)-1]='\0';
            }else{
                HILOG_INFO(LOG_CORE,"upgrade error");
                ret = -1;
                break;                
            } 
            if((temp = cJSON_GetObjectItemCaseSensitive(json,"recordFileName")) != NULL){
                strncpy(pDeviceInfo->recordFileName,cJSON_GetStringValue(temp),sizeof(pDeviceInfo->recordFileName));
                pDeviceInfo->recordFileName[sizeof(pDeviceInfo->recordFileName)-1]='\0';
            }else{
                HILOG_INFO(LOG_CORE,"upgrade error");
                ret = -1;
                break;                
            }                          
            if((temp = cJSON_GetObjectItemCaseSensitive(json,"statusFileName")) != NULL){
                strncpy(pDeviceInfo->statusFileName,cJSON_GetStringValue(temp),sizeof(pDeviceInfo->statusFileName));
                pDeviceInfo->statusFileName[sizeof(pDeviceInfo->statusFileName)-1]='\0';
            } else{
                HILOG_INFO(LOG_CORE,"upgrade error");
                ret = -1;
                break;                
            }                                    
        }
        else{
            HILOG_INFO(LOG_CORE,"upgrade error");
            ret = -1;
            break;                
        }

        if((json = cJSON_GetObjectItemCaseSensitive(root,"logInfo")) != NULL){

            if((temp = cJSON_GetObjectItemCaseSensitive(json,"logFile")) != NULL){
                strncpy(pDeviceInfo->logFile,cJSON_GetStringValue(temp),sizeof(pDeviceInfo->logFile));
                pDeviceInfo->logFile[sizeof(pDeviceInfo->logFile)-1]='\0';
            }

            if((temp = cJSON_GetObjectItemCaseSensitive(json,"logFileMaxSize")) != NULL){
                pDeviceInfo->logFileMaxSize = cJSON_GetNumberValue(temp);
            }

            if((temp = cJSON_GetObjectItemCaseSensitive(json,"logLevel")) != NULL){
                pDeviceInfo->logLevel = cJSON_GetNumberValue(temp);
            }
        }      
    }while(0);
    cJSON_Delete(root);
    return ret;
}

/**********************************************************************************/


UpdateLiteCallback* mcallback;
downloadCallback* mdownloadPkgCallback;
downloadCallback* mdownloadInfoCallback;

//base data type
typedef int            HW_INT;  /**< Indicates type of int. */
typedef unsigned int   HW_UINT; /**< Indicates type of unsigned int. */
typedef char           HW_CHAR; /**< Indicates type of char. */
typedef unsigned char  HW_UCHAR;/**< Indicates type of unsigned char. */
typedef int            HW_BOOL; /**< Indicates type of HW_BOOL. */
typedef void           HW_VOID; /**< Indicates type of void. */

#define IOTA_BUF_SIZE_512		512

//
#define TOKEN "HIPH3519"
//#define ADDRESS "tcp://mqtt.eclipseprojects.io:1883"
//#define ADDRESS "tcp://60.204.219.164:1883"
//#define ADDRESS "tcp://44.232.241.40:1883"
#define ADDRESS "tcp://10.50.80.72:1883"

//mqtt
static MQTTAsync g_client = NULL;
static HW_CHAR g_pcCertPath[IOTA_BUF_SIZE_512] = { 0 };



typedef HW_VOID(*PFN_CALLBACK_HANDLER)(HW_VOID* context, HW_INT messageId, HW_INT code, HW_CHAR* message);

static PFN_CALLBACK_HANDLER g_pfnCbConnectionLost = NULL;


void * g_context = NULL ;
static int isconnect = 0;

/*
// 定义结构体
typedef struct {
    int msgId;
    int msgType;
    char msgTypeName[50];
    struct {
        char url[50];
        char otaType[50];
        char fileName[50];
        char sha256Hex[50];
    } msgInfo;
} OTAMessage;

OTAMessage otamsg;


// 初始化结构体
void initMessage(OTAMessage *msg) {
    msg->msgId = 0;
    msg->msgType = 0;
    strncpy(msg->msgTypeName, "", sizeof(msg->msgTypeName));
    strncpy(msg->msgInfo.url, "", sizeof(msg->msgInfo.url));
    strncpy(msg->msgInfo.otaType, "", sizeof(msg->msgInfo.otaType));
    strncpy(msg->msgInfo.fileName, "", sizeof(msg->msgInfo.fileName));
    strncpy(msg->msgInfo.sha256Hex, "", sizeof(msg->msgInfo.sha256Hex));
}

// 解析JSON内容并为结构体赋值
int parseJSONToMessage(const char *json, OTAMessage *msg) {
    cJSON *root = cJSON_Parse(json);
    if (root == NULL) {
        const char *error_ptr = cJSON_GetErrorPtr();
        if (error_ptr != NULL) {
            fprintf(stderr, "Error before: %s\n", error_ptr);
        }
        return -1; // 解析错误
    }

    cJSON *msgId_json = cJSON_GetObjectItemCaseSensitive(root, "msgId");
    cJSON *msgType_json = cJSON_GetObjectItemCaseSensitive(root, "msgType");
    cJSON *msgTypeName_json = cJSON_GetObjectItemCaseSensitive(root, "msgTypeName");
    cJSON *msgInfo_json = cJSON_GetObjectItemCaseSensitive(root, "msgInfo");

    if (cJSON_IsNumber(msgId_json)) {
        msg->msgId = msgId_json->valueint;
    }
    if (cJSON_IsNumber(msgType_json)) {
        msg->msgType = msgType_json->valueint;
    }
    if (msgTypeName_json && (msgTypeName_json->type & cJSON_String)) {
        strncpy(msg->msgTypeName, msgTypeName_json->valuestring, sizeof(msg->msgTypeName) - 1);
        msg->msgTypeName[sizeof(msg->msgTypeName) - 1] = '\0'; // 确保字符串以空字符结尾
    }

    if (msgInfo_json) {
        cJSON *url_json = cJSON_GetObjectItemCaseSensitive(msgInfo_json, "url");
        cJSON *otaType_json = cJSON_GetObjectItemCaseSensitive(msgInfo_json, "otaType");
        cJSON *fileName_json = cJSON_GetObjectItemCaseSensitive(msgInfo_json, "fileName");
        cJSON *sha256Hex_json = cJSON_GetObjectItemCaseSensitive(msgInfo_json, "sha256Hex");

        if (url_json && (url_json->type & cJSON_String)) {
            strncpy(msg->msgInfo.url, url_json->valuestring, sizeof(msg->msgInfo.url) - 1);
            msg->msgInfo.url[sizeof(msg->msgInfo.url) - 1] = '\0';
        }
        if (otaType_json && (otaType_json->type & cJSON_String)) {
            strncpy(msg->msgInfo.otaType, otaType_json->valuestring, sizeof(msg->msgInfo.otaType) - 1);
            msg->msgInfo.otaType[sizeof(msg->msgInfo.otaType) - 1] = '\0';
        }
        if (fileName_json && (fileName_json->type & cJSON_String)) {
            strncpy(msg->msgInfo.fileName, fileName_json->valuestring, sizeof(msg->msgInfo.fileName) - 1);
            msg->msgInfo.fileName[sizeof(msg->msgInfo.fileName) - 1] = '\0';
        }
        if (sha256Hex_json && (sha256Hex_json->type & cJSON_String)) {
            strncpy(msg->msgInfo.sha256Hex, sha256Hex_json->valuestring, sizeof(msg->msgInfo.sha256Hex) - 1);
            msg->msgInfo.sha256Hex[sizeof(msg->msgInfo.sha256Hex) - 1] = '\0';
        }
    }

    cJSON_Delete(root); // 释放cJSON对象占用的内存
    return 0; // 解析成功
}


// 打印结构体内容（用于验证）
void printMessage(const OTAMessage *msg) {
    HILOG_INFO(LOG_CORE, "mqtt_ota.c ---- .... delivered----msgId: %d\n", msg->msgId);
    HILOG_INFO(LOG_CORE, "mqtt_ota.c ---- .... delivered----msgType: %d\n", msg->msgType);
    HILOG_INFO(LOG_CORE, "mqtt_ota.c ---- .... delivered----msgTypeName: %s\n", msg->msgTypeName);
    HILOG_INFO(LOG_CORE, "mqtt_ota.c ---- .... delivered----msgInfo.url: %s\n", msg->msgInfo.url);
    HILOG_INFO(LOG_CORE, "mqtt_ota.c ---- .... delivered----msgInfo.otaType: %s\n", msg->msgInfo.otaType);
    HILOG_INFO(LOG_CORE, "mqtt_ota.c ---- .... delivered----msgInfo.fileName: %s\n", msg->msgInfo.fileName);
    HILOG_INFO(LOG_CORE, "mqtt_ota.c ---- .... delivered----msgInfo.sha256Hex: %s\n", msg->msgInfo.sha256Hex);
}
*/

typedef struct {
    char appId[50];
    int otaType;
    char subpackageName[50]; // 注意修正了原结构体中的拼写错误
    char sha256Hex[50];
} SubPackageInfo;

typedef struct {
    int msgId;
    int msgType;
    int num; // 注意：这个字段在解析时可能不会被直接使用，而是作为校验
    char baleFileName[50];
    char balePackName[50];
    char url[200];
    char balesha256Hex[50];
    // 使用指针和动态分配的内存来处理subpackage数组
    SubPackageInfo *subpackages;
    int subpackageCount; // 实际解析出的subpackage数量
} OTAMessage;

// 初始化Message结构体到默认状态
void initMessage(OTAMessage *msg) {
    if (msg) {
        msg->msgId = 0;
        msg->msgType = 0;
        msg->num = 0;
        memset(msg->baleFileName, 0, sizeof(msg->baleFileName));
        memset(msg->balePackName, 0, sizeof(msg->balePackName));
        memset(msg->url, 0, sizeof(msg->url));
        memset(msg->balesha256Hex, 0, sizeof(msg->balesha256Hex));
        msg->subpackages = NULL;
        msg->subpackageCount = 0;
    }
}

void parseJSONToMessage(const char *json, OTAMessage *msg) {
    // 检查输入参数是否为空，若为空则直接返回
    if (!json || !msg) return;
 
    // 解析JSON字符串为cJSON对象
    cJSON *root = cJSON_Parse(json);
    // 如果解析失败，则打印错误信息并返回
    if (!root) {
        printf("JSON解析错误\n");
        return;
    }
 
    // 解析Message字段
    cJSON *msgId_json = cJSON_GetObjectItem(root, "msgId");       // 获取msgId字段
    cJSON *msgType_json = cJSON_GetObjectItem(root, "msgType");   // 获取msgType字段
    cJSON *num_json = cJSON_GetObjectItem(root, "num");           // 获取num字段（注意：此字段可能不直接使用）
    cJSON *baleFileName_json = cJSON_GetObjectItem(root, "baleFileName"); // 获取baleFileName字段
    cJSON *balePackName_json = cJSON_GetObjectItem(root, "balePackName"); // 获取balePackName字段
    cJSON *url_json = cJSON_GetObjectItem(root, "url");           // 获取url字段
    cJSON *balesha256Hex_json = cJSON_GetObjectItem(root, "balesha256Hex"); // 获取balesha256Hex字段
 
    // 如果msgId是数字类型，则将其值赋给Message结构体的msgId字段
    if (cJSON_IsNumber(msgId_json)) msg->msgId = msgId_json->valueint;
    // 如果msgType是数字类型，则将其值赋给Message结构体的msgType字段
    if (cJSON_IsNumber(msgType_json)) msg->msgType = msgType_json->valueint;
    // msg->num字段目前被忽略，但以后可能用于验证
    // 如果baleFileName是字符串类型且长度小于Message结构体中baleFileName数组的大小，则将其值复制到baleFileName字段中
    if (cJSON_IsString(baleFileName_json) && strlen(baleFileName_json->valuestring) < sizeof(msg->baleFileName)) {
        strncpy(msg->baleFileName, baleFileName_json->valuestring, sizeof(msg->baleFileName) - 1);
    }
    // 如果balePackName是字符串类型且长度小于Message结构体中balePackName数组的大小，则将其值复制到balePackName字段中
    if (cJSON_IsString(balePackName_json) && strlen(balePackName_json->valuestring) < sizeof(msg->balePackName)) {
        strncpy(msg->balePackName, balePackName_json->valuestring, sizeof(msg->balePackName) - 1);
    }
    // 如果url是字符串类型且长度小于Message结构体中url数组的大小，则将其值复制到url字段中
    if (cJSON_IsString(url_json) && strlen(url_json->valuestring) < sizeof(msg->url)) {
        strncpy(msg->url, url_json->valuestring, sizeof(msg->url) - 1);
    }
    // 如果balesha256Hex是字符串类型且长度小于Message结构体中balesha256Hex数组的大小，则将其值复制到balesha256Hex字段中
    if (cJSON_IsString(balesha256Hex_json) && strlen(balesha256Hex_json->valuestring) < sizeof(msg->balesha256Hex)) {
        strncpy(msg->balesha256Hex, balesha256Hex_json->valuestring, sizeof(msg->balesha256Hex) - 1);
    }
 
    // 解析子包数组
    cJSON *subpackages_json = cJSON_GetObjectItem(root, "subpackage");
    if (cJSON_IsArray(subpackages_json)) { // 如果subpackage是数组类型
        int subpackageArraySize = cJSON_GetArraySize(subpackages_json); // 获取子包数组的大小
        msg->subpackages = (SubPackageInfo *)malloc(subpackageArraySize * sizeof(SubPackageInfo)); // 为子包数组分配内存
        if (msg->subpackages) { // 如果内存分配成功
            cJSON *item;
            cJSON_ArrayForEach(item, subpackages_json) { // 遍历子包数组
                SubPackageInfo *subpkg = &msg->subpackages[msg->subpackageCount++]; // 获取当前子包的指针并递增子包计数器
                memset(subpkg, 0, sizeof(SubPackageInfo)); // 在填充之前将结构体清零
 
                cJSON *appId_json = cJSON_GetObjectItem(item, "appId");           // 获取appId字段
                cJSON *otaType_json = cJSON_GetObjectItem(item, "otaType");       // 获取otaType字段
                cJSON *subpackageName_json = cJSON_GetObjectItem(item, "subpackageName"); // 获取subpackageName字段
                cJSON *sha256Hex_json = cJSON_GetObjectItem(item, "sha256Hex");   // 获取sha256Hex字段
 
                // 如果appId是字符串类型且长度小于SubPackageInfo结构体中appId数组的大小，则将其值复制到appId字段中
                if (cJSON_IsString(appId_json) && strlen(appId_json->valuestring) < sizeof(subpkg->appId)) {
                    strncpy(subpkg->appId, appId_json->valuestring, sizeof(subpkg->appId) - 1);
                }
                // 如果otaType是数字类型，则将其值赋给SubPackageInfo结构体的otaType字段
                if (cJSON_IsNumber(otaType_json)) subpkg->otaType = otaType_json->valueint;
                // 如果subpackageName是字符串类型且长度小于SubPackageInfo结构体中subpackageName数组的大小，则将其值复制到subpackageName字段中
                if (cJSON_IsString(subpackageName_json) && strlen(subpackageName_json->valuestring) < sizeof(subpkg->subpackageName)) {
                    strncpy(subpkg->subpackageName, subpackageName_json->valuestring, sizeof(subpkg->subpackageName) - 1);
                }
                // 如果sha256Hex是字符串类型且长度小于SubPackageInfo结构体中sha256Hex数组的大小，则将其值复制到sha256Hex字段中
                if (cJSON_IsString(sha256Hex_json) && strlen(sha256Hex_json->valuestring) < sizeof(subpkg->sha256Hex)) {
                    strncpy(subpkg->sha256Hex, sha256Hex_json->valuestring, sizeof(subpkg->sha256Hex) - 1);
                }
            }
        } else { // 如果内存分配失败，则打印错误信息
            printf("子包内存分配失败\n");
        }
    }
 
    // 清理（释放cJSON解析器分配的内存）
    cJSON_Delete(root);
}

// 打印 Message 结构体的函数
void printMessage(const OTAMessage *msg) {
    if (msg == NULL) {
        HILOG_INFO(LOG_CORE, "OTAMessage pointer is NULL\n");
        return;
    }
 
    HILOG_INFO(LOG_CORE, "OTAMessage ID: %d\n", msg->msgId);
    HILOG_INFO(LOG_CORE, "OTAMessage Type: %d\n", msg->msgType);
    HILOG_INFO(LOG_CORE, "Num (for checksum): %d\n", msg->num);
    HILOG_INFO(LOG_CORE, "Bale File Name: %s\n", msg->baleFileName);
    HILOG_INFO(LOG_CORE, "Bale Pack Name: %s\n", msg->balePackName);
    HILOG_INFO(LOG_CORE, "URL: %s\n", msg->url);
    HILOG_INFO(LOG_CORE, "Bale SHA256 Hex: %s\n", msg->balesha256Hex);
 
    HILOG_INFO(LOG_CORE, "Subpackages Count: %d\n", msg->subpackageCount);
    for (int i = 0; i < msg->subpackageCount; i++) {
        const SubPackageInfo *subpackage = &msg->subpackages[i];
        HILOG_INFO(LOG_CORE, "  SubPackage %d:\n", i + 1);
        HILOG_INFO(LOG_CORE, "    App ID: %s\n", subpackage->appId);
        HILOG_INFO(LOG_CORE, "    OTA Type: %d\n", subpackage->otaType);
        HILOG_INFO(LOG_CORE, "    SubPackage Name: %s\n", subpackage->subpackageName);
        HILOG_INFO(LOG_CORE, "    SHA256 Hex: %s\n", subpackage->sha256Hex);
    }
}

// 释放Message结构体中动态分配的内存
void freeMessage(OTAMessage *msg) {
    if (msg) {
        free(msg->subpackages);
        msg->subpackages = NULL;
        msg->subpackageCount = 0;
        // 不需要释放其他字段，因为它们不是动态分配的
    }
}



static void delivered(void* context, MQTTAsync_token dt)
{
	//writeLog(2, "Message with token value %d delivery confirmed\n", dt);
    HILOG_INFO(LOG_CORE, "mqtt_ota.c ---- .... delivered----dt = %d\n", dt);
}

OTAMessage otamsg;

static int msgarrived(void* context, char* topicName, int topicLen, MQTTAsync_message* message)
{
    HILOG_INFO(LOG_CORE, "mqtt_ota.c ---- .... msgarrived\n");
	int iRet = 1;
    
	((char*)message->payload)[message->payloadlen] = '\0';
	HILOG_INFO(LOG_CORE, "mqtt_ota.c ---- Message msgarrived, topic: %s, topicLen: %d, len: %d, msgid: %d, message:\n %s\n", topicName, topicLen, message->payloadlen, message->msgid, (char*)message->payload);

    initMessage(&otamsg);
    printMessage(&otamsg);
    HILOG_INFO(LOG_CORE, "mqtt_ota.c ---- .... msgarrived----------------------after initMessage\n");
    parseJSONToMessage(message->payload, &otamsg);
    printMessage(&otamsg);

    char fileallpath[256];
    snprintf(fileallpath, sizeof(fileallpath), "%s%s", "/userdata/", otamsg.baleFileName);
    HILOG_INFO(LOG_CORE, "mqtt_ota.c ---- .... msgarrived------The full file path is: %s\n", fileallpath);
    int downret = curlDownload(otamsg.url, fileallpath, NULL);
    //if (downret == -1) return -1;
    int checkret = downret; 
    if (checkret != 0)
    {
        HILOG_INFO(LOG_CORE, "mqtt_ota.c ---- .... msgarrived------checkret == -1 \n");
        unlink(fileallpath);
        return -1;
    } else {
        char tarcommand[512];
        snprintf(tarcommand, sizeof(tarcommand), "cd \"/userdata/\" && tar -xzvf \"%s\"", otamsg.baleFileName);
        HILOG_INFO(LOG_CORE, "mqtt_ota.c ---- .... msgarrived--------command : %s \n", tarcommand);
        int tarresult = system(tarcommand);
        if(tarresult == -1)
        {
            HILOG_INFO(LOG_CORE, "mqtt_ota.c ---- .... msgarrived------tarresult == -1 \n");
            perror("system");
            checkret = -1;
        } else {
            if (WIFEXITED(tarresult)) {
                HILOG_INFO(LOG_CORE, "mqtt_ota.c ---- .... msgarrived------tarresult--WIFEXITED(result) \n");
            } else {
                HILOG_INFO(LOG_CORE, "mqtt_ota.c ---- .... msgarrived------tarresult--tarCommand did not exit normally\n");
                checkret = -1;
            }
        }
    }

    HILOG_INFO(LOG_CORE, "mqtt_ota.c ---- .... msgarrived------print otamsg subpackage\n");
    for (int i = 0; i < otamsg.subpackageCount; i++) {
        const SubPackageInfo *subpackage = &otamsg.subpackages[i];
        HILOG_INFO(LOG_CORE, "  SubPackage %d:\n", i + 1);
        HILOG_INFO(LOG_CORE, "    App ID: %s\n", subpackage->appId);
        HILOG_INFO(LOG_CORE, "    OTA Type: %d\n", subpackage->otaType);
        HILOG_INFO(LOG_CORE, "    SubPackage Name: %s\n", subpackage->subpackageName);
        HILOG_INFO(LOG_CORE, "    SHA256 Hex: %s\n", subpackage->sha256Hex);
    }

    HILOG_INFO(LOG_CORE, "mqtt_ota.c ---- .... msgarrived------to run appm or sysupdate \n");
    for (int i = 0; i < otamsg.subpackageCount; i++) {
        const SubPackageInfo *subpackage = &otamsg.subpackages[i];
        memset(fileallpath, 0, sizeof(fileallpath));
        snprintf(fileallpath, sizeof(fileallpath), "%s%s%s%s", "/userdata/", otamsg.balePackName, "/", subpackage->subpackageName);
        HILOG_INFO(LOG_CORE, "mqtt_ota.c ---- .... msgarrived------The full file path is: %s\n", fileallpath);
        if(subpackage->otaType == 1)
        {
            HILOG_INFO(LOG_CORE, "mqtt_ota.c ---- .... msgarrived--------using sysupdate,  otaType = %d\n", subpackage->otaType);
            char command[256];
            snprintf(command, sizeof(command), "sysupdate -i -p %s", fileallpath);
            HILOG_INFO(LOG_CORE, "mqtt_ota.c ---- .... msgarrived--------command : %s \n", command);
            int result = system(command);
            if(result == -1)
            {
                perror("system");
            } else {
                if (WIFEXITED(result)) {
                    HILOG_INFO(LOG_CORE, "mqtt_ota.c ---- .... msgarrived----sysupdate----WIFEXITED(result) \n");
                    /**************************************************************************
                     * reboot
                    ****/
                    memset(command, 0, sizeof(command));
                    snprintf(command, sizeof(command), "reboot");
                    HILOG_INFO(LOG_CORE, "mqtt_ota.c ---- .... msgarrived----sysupdate----to reboot \n");
                    int rebootret = system(command);
                    if(rebootret == -1){
                        HILOG_INFO(LOG_CORE, "mqtt_ota.c ---- .... msgarrived----sysupdate----rebootret == -1 \n");
                    } else {
                        HILOG_INFO(LOG_CORE, "mqtt_ota.c ---- .... msgarrived----sysupdate----rebootret != -1 \n");
                    }
                    /***************************************************************************/
                } else {
                    HILOG_INFO(LOG_CORE, "mqtt_ota.c ---- .... msgarrived----sysupdate----Command did not exit normally\n");
                }
            }
        } else {
            HILOG_INFO(LOG_CORE, "mqtt_ota.c ---- .... msgarrived--------using appm,  otaType = %d\n", subpackage->otaType);
            char command[256];
            snprintf(command, sizeof(command), "appm -i -p %s", fileallpath);
            HILOG_INFO(LOG_CORE, "mqtt_ota.c ---- .... msgarrived--------command : %s \n", command);
            int result = system(command);
            if(result == -1)
            {
                perror("system");
            } else {
                if (WIFEXITED(result)) {
                    HILOG_INFO(LOG_CORE, "mqtt_ota.c ---- .... msgarrived----appm----WIFEXITED(result) \n");
                } else {
                    HILOG_INFO(LOG_CORE, "mqtt_ota.c ---- .... msgarrived----appm----Command did not exit normally\n");
                }
            }
        }
    }

    HILOG_INFO(LOG_CORE, "mqtt_ota.c ---- .... msgarrived--------to freeMessage(&otamsg)\n");
    freeMessage(&otamsg);
	MQTTAsync_freeMessage(&message);
	MQTTAsync_free(&topicName);
    HILOG_INFO(LOG_CORE, "mqtt_ota.c ---- .... msgarrived--------after freeMessage(&otamsg)\n");
	return iRet;
}

static void onSendSuccess(void* context, MQTTAsync_successData* response)
{
	HILOG_INFO(LOG_CORE, "onSendSuccess! token: %d", response->token);

	// if (g_pfnCbPublishSuccess)
	// {
	// 	g_pfnCbPublishSuccess(context, 0, 0,NULL, "",0);
	// }
}

static void onSendFailure(void* context, MQTTAsync_failureData* response)
{
	HILOG_INFO(LOG_CORE, "onSendFailure! token: %d, code: %d, message = %s", response->token, response->code, response->message);

	// if (g_pfnCbPublishFailure)
	// {
	// 	g_pfnCbPublishFailure(context, 0, response->code, NULL,(char*)response->message,0);
	// }
}

int MQTT_publishMessage(char* pcTopicName, char* pcMessage,unsigned int uiQos)
{
	if (!g_client)
	{
		HILOG_INFO(LOG_CORE, "Failed to MQTT_publishMessage g_client is %p", g_client);
		return -1;
	}
	int iRet = 0;
	MQTTAsync_message pubmsg = MQTTAsync_message_initializer;
	//MQTTAsync_token token;

	pubmsg.payload = (void*)pcMessage;
	pubmsg.payloadlen = strlen(pcMessage);
	pubmsg.qos = uiQos;
	pubmsg.retained = 0;

	MQTTAsync_responseOptions opts = MQTTAsync_responseOptions_initializer;
	opts.onSuccess = onSendSuccess;
	opts.onFailure = onSendFailure;
	opts.context = g_context;
    HILOG_INFO(LOG_CORE, "mqtt_ota.c ---- .... MQTT_publishMessage--------to sendmsg\n");
	iRet = MQTTAsync_sendMessage(g_client, pcTopicName, &pubmsg, &opts);
	if (iRet != MQTTASYNC_SUCCESS)
	{
		HILOG_INFO(LOG_CORE, "Failed to publish message, return code %d", iRet);
		iRet = -1;
	}
	else
	{
		HILOG_INFO(LOG_CORE,  "MQTTAsync_sendMessage, topic: %s,qos:%u\n%s", pcTopicName,uiQos, pcMessage);
	}
    HILOG_INFO(LOG_CORE, "mqtt_ota.c ---- .... MQTT_publishMessage--------after sendmsg\n");
	return iRet;
}

static void onSubscribeSuccess(void* context, MQTTAsync_successData* response)
{
	HILOG_INFO(LOG_CORE, "mqtt_ota.c ----onSubscribeSuccess! token: %d\n", response->token);

	// if (g_pfnCbSubscribeSuccess)
	// {
	// 	g_pfnCbSubscribeSuccess(NULL, 0, 0, "");
	// }
}

static void onSubscribeFailure(void* context, MQTTAsync_failureData* response)
{
	HILOG_INFO(LOG_CORE, "mqtt_ota.c ----onSubscribeFailure! token: %d, code: %d, message = %s\n", response->token, response->code, response->message);

	// if (g_pfnCbSubscribeFailure)
	// {
	// 	g_pfnCbSubscribeFailure(NULL, 0, response->code, (HW_CHAR*)response->message);
	// }
}


//#define RPC_REQUEST_TOPIC BASE_TOPIC "rpc/request/+"
static unsigned int g_uiQos = 0;

static void subscribeTopic(void)
{
    // strcpy(g_pcTopicCommand,RPC_REQUEST_TOPIC);
	// char* arraySubs[4];
	// arraySubs[0] = g_pcTopicTopoAddResponse;
	// arraySubs[1] = g_pcTopicTopoUpdateResponse;
	// arraySubs[2] = g_pcTopicTopoQueryResponse;
	// arraySubs[3] = g_pcTopicCommand;
    HILOG_INFO(LOG_CORE, "mqtt_ota.c ---- .... subscribeTopic-----RECV_TOPIC: %s\n", RECV_TOPIC);

    

	int iRet = 0;
	// for (int i = 0; i < 4; i++)
	// {
    //     if(strlen(arraySubs[i])==0)
    //         continue;

		MQTTAsync_responseOptions opts = MQTTAsync_responseOptions_initializer;
		opts.onSuccess = onSubscribeSuccess;
		opts.onFailure = onSubscribeFailure;
		opts.context = NULL;
		//iRet = MQTTAsync_subscribe(g_client, "qwertyui654321", g_uiQos, &opts);    //RPC_REQUEST_PREFIX
        iRet = MQTTAsync_subscribe(g_client, RECV_TOPIC, g_uiQos, &opts);
		if (iRet != MQTTASYNC_SUCCESS)
		{
			HILOG_INFO(LOG_CORE, "mqtt_ota.c ---- .... subscribeTopic--------Failed to subscribe, return code %d\n", iRet);
		}
        HILOG_INFO(LOG_CORE, "mqtt_ota.c ---- .... subscribeTopic\n");
		// else
		// {
		// 	writeLog(2, "MQTTAsync_subscribe, topic: %s\n", arraySubs[i]);
		// }
	// }
}

static void onConnectSuccess(void* context, MQTTAsync_successData* response)
{
	HILOG_INFO(LOG_CORE, "mqtt_ota.c ---- .... onConnectSuccess----- token: %d\n", response->token);
    isconnect = 1;
    g_context = context;

    //MQTT_publishMessage("qwertyui654321", "{\"PA\":\"22.54845664\",\"TEM\":\"114.06455184\"}",0);

	// if (g_pfnCbConnectSuccess)
	// {
	// 	g_pfnCbConnectSuccess(NULL, 0, 0, "");
	// }

	subscribeTopic();
    //reportIPCAttrInfo();
}

int MQTT_connect();

static void onConnectFailure(void* context, MQTTAsync_failureData* response)
{
	HILOG_INFO(LOG_CORE, "mqtt_ota.c ---- .... onConnectFailure----- token: %d, code: %d, message = %s\n", response->token, response->code, response->message);
    isconnect = 0;

	// if (g_pfnCbConnectFailure)
	// {
	// 	g_pfnCbConnectFailure(NULL, 0, response->code, (HW_CHAR*)response->message);
    //     return;
	// }
	sleep(3);
    MQTT_connect();
    return;
}

int MQTT_connect()
{
    HILOG_INFO(LOG_CORE, "mqtt_ota.c ---- .... MQTT_connect\n");
    // MQTTAsync_SSLOptions ssl_opts = MQTTAsync_SSLOptions_initializer;
    // ssl_opts.trustStore = strlen(g_pcCertPath) == 0 ? "./mqttClientTrustCert.pem" : g_pcCertPath;
    // ssl_opts.sslVersion = MQTT_SSL_VERSION_DEFAULT;

    MQTTAsync_connectOptions conn_opts = MQTTAsync_connectOptions_initializer;
    conn_opts.keepAliveInterval = 20;
    conn_opts.onSuccess = onConnectSuccess;
    conn_opts.onFailure = onConnectFailure;
    conn_opts.username = TOKEN;
    conn_opts.password = NULL;
    conn_opts.context = NULL;
    //conn_opts.ssl = &ssl_opts;
    conn_opts.ssl = NULL;
    int iRet = MQTTAsync_connect(g_client, &conn_opts);
    if (iRet != MQTTASYNC_SUCCESS)
    {
        HILOG_INFO(LOG_CORE, "mqtt_ota.c ---- .... MQTT_connect return code %d\n", iRet);
    }
    HILOG_INFO(LOG_CORE, "mqtt_ota.c ---- .... MQTT_connect------- return iRet \n");
    return iRet;
}

static void connlost(void* context, char* cause)
{
	//writeLog(2, "Connection lost! cause: %s\n", cause);
    HILOG_INFO(LOG_CORE, "mqtt_ota.c ---- .... InitMQTTConnect-----cause: %s\n", cause);
	if (g_pfnCbConnectionLost)
	{
		g_pfnCbConnectionLost(NULL, 0, 0, cause);
        return;
	}
    MQTT_connect();
}

uint32_t InitMQTTConnect(UpdateLiteCallback callback)
{
    HILOG_INFO(LOG_CORE, "mqtt_ota.c ---- .... InitMQTTConnect\n");
    mcallback = callback;
    // ThreadAttr attr = {"collector thread", 1024, 2, 0, 0};
    // ThreadId threadId = (ThreadId)THREAD_Create(MQTTThreadCallback, NULL, &attr);

	//	创建mqtt
	char client_id[24];
	snprintf(client_id, sizeof(client_id), "client_%ld", time(NULL));

    int iRet = 0;
    iRet = MQTTAsync_create(&g_client, ADDRESS, client_id, MQTTCLIENT_PERSISTENCE_NONE, NULL);
    if (iRet != MQTTASYNC_SUCCESS)
	{
		HILOG_INFO(LOG_CORE, "mqtt_ota.c ---- .... InitMQTTConnect------MQTTAsync_create----iRet = %d\n", iRet);
		return -1;
	}
    HILOG_INFO(LOG_CORE, "mqtt_ota.c ---- .... InitMQTTConnect-------after MQTTAsync_create\n");

    iRet = MQTTAsync_setCallbacks(g_client, NULL, connlost, msgarrived, delivered);
	if (iRet != MQTTASYNC_SUCCESS)
	{
        HILOG_INFO(LOG_CORE, "mqtt_ota.c ---- .... InitMQTTConnect------MQTTAsync_setCallbacks----iRet = %d\n", iRet);
		return -1;
	}
    HILOG_INFO(LOG_CORE, "mqtt_ota.c ---- .... InitMQTTConnect-------after MQTTAsync_setCallbacks\n");

    MQTT_connect();

    HILOG_INFO(LOG_CORE, "mqtt_ota.c ---- .... InitMQTTConnect--------to return 0 \n");
    return 0;
}


struct MemoryStruct {
  char *memory;
  size_t size;
};
struct MemoryStruct mms;
UpdateLiteInfo minfo;
uint32_t GetFirmwareInfo(struct UpdateLiteInfo *info, char* url, downloadCallback callback)
{
    HILOG_INFO(LOG_CORE, "mqtt_ota.c ---- .... GetFirmwareInfo-------url: %s\n", url);
    //MQTT_publishMessage(SEND_TOPIC, getFirmwareInfoJSON, 0);
    mms.memory = malloc(1); 
    mms.size = 0;
    int ret = curlDownload(url, NULL, &mms);
    minfo.msgtype = 3;
    minfo.transType = 1;
    minfo.msgid = 0;
    minfo.payload = (uint8_t*)mms.memory;
    //minfo.payload = NULL;
    minfo.payloadlen = mms.size;
    HILOG_INFO(LOG_CORE, "mqtt_ota.c ---- .... GetFirmwareInfo-------2\n");
    callback(&minfo, ret);
    //HILOG_INFO(LOG_CORE, "mqtt_ota.c ---- .... GetFirmwareInfo-------3\n");
    free(minfo.payload);
    minfo.payloadlen = 0;
    return 0;
}

// curl回调函数  
static size_t WriteMemoryCallback(void *contents, size_t size, size_t nmemb, void *userp)
{
  size_t realsize = size * nmemb;
  struct MemoryStruct *mem = (struct MemoryStruct *)userp;
 
 // 注意这里根据每次被调用获得的数据重新动态分配缓存区的大小
  char *ptr = realloc(mem->memory, mem->size + realsize + 1);
  if(ptr == NULL) {
    /* out of memory! */ 
    HILOG_INFO(LOG_CORE,"not enough memory (realloc returned NULL)");
    return 0;
  }
 
  mem->memory = ptr;
  memcpy(&(mem->memory[mem->size]), contents, realsize);
  mem->size += realsize;
  mem->memory[mem->size] = 0;

  if (0)
  {
    //printf("\n%s\n",(char*)contents);
    HILOG_INFO(LOG_CORE,"\n%s\n",(char *)contents);
  }
  else
    HILOG_INFO(LOG_CORE,"WriteMemoryCallback(%ld)\n%s",realsize,(char *)contents);

  return realsize;
}

// curl进度回调函数  
static int curlDownloadCallback(void *clientp, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow)  
{
    //HILOG_INFO(LOG_CORE, "mqtt_ota.c ---- .... progress_callback--------dltotal =  %.2f%%, dlnow =   %.2f%%\n", dltotal, dlnow);
    double percent;  
    static double lastPercent = 0; 
    // 如果总下载大小未知，则不显示百分比  
    if(dltotal == 0)  
        return 0;  
    
    percent = (double)dlnow / dltotal * 100.0;  
    //HILOG_INFO(LOG_CORE,"mqtt_ota.c ---- .... progress_callback--------Downloaded %.2f%% of the file\n", percent);
    if ((percent -lastPercent) > 5)
    {
        lastPercent = percent;
        HILOG_INFO(LOG_CORE,"mqtt_ota.c ---- .... progress_callback--------Downloaded %.2f%% of the file\n", percent);
    }  
    // 返回0表示继续
    //这里可以再调用上一级的callback函数进行进度反馈
    return 0;  
}  

int curlDownload(const char *url,const char *fileName, struct MemoryStruct *chunk)
{
    CURL *curl = NULL;
    CURLcode res;
    int ret = 0;
    FILE *fp = NULL;  
    HILOG_INFO(LOG_CORE, "mqtt_ota.c ---- .... curlDownload------url: %s\n", url);
    curl_global_init(CURL_GLOBAL_DEFAULT);
    curl = curl_easy_init();
    if (curl)
    {
        res = curl_easy_setopt(curl, CURLOPT_URL, url);
        if (fileName)
        {
            HILOG_INFO(LOG_CORE,"file %s",fileName);
            // 打开文件用于写入  
            fp = fopen(fileName, "wb");
            if(fp == NULL) {  
                // 错误处理  
                HILOG_INFO(LOG_CORE,"Failed to open file %s",fileName);
                ret = -1;  
            }
            else
            {
                // 设置文件指针  
                res |= curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
                // 启用进度回调函数  
                res |= curl_easy_setopt(curl, CURLOPT_XFERINFOFUNCTION, curlDownloadCallback);
                // 启用进度跟踪  
                res |= curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0L);
                // 当HTTP返回值大于等于400的时候，请求失败
                ret |= curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1L);
                res |= curl_easy_perform(curl);

                // 关闭文件  
                fclose(fp);                  
            }
        }
        else
        {
            HILOG_INFO(LOG_CORE, "mqtt_ota.c ---- .... curlDownload-----else\n");
            res |= curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
            res |= curl_easy_setopt(curl, CURLOPT_WRITEDATA, chunk);
            res |= curl_easy_perform(curl);
        }

        if (res != CURLE_OK)
        {
            HILOG_INFO(LOG_CORE, "curl_easy_perform() failed: %s", curl_easy_strerror(res));
            ret = -1;  
        } 
        
        curl_easy_cleanup(curl);

    }
    curl_global_cleanup();
    return ret;
}

static void *MQTTDownloadThread(void *argv)
{
    //while (1) {
    //    sleep(5);
        HILOG_INFO(LOG_CORE, "mqtt_ota.c ---- .... MQTTDownloadThread\n");

        const char *firmwarefilename = "/userdata/upgrade/updater.zip";
        int ret = curlDownload(firmwarePkgUrl, firmwarefilename, NULL);

        HILOG_INFO(LOG_CORE, "mqtt_ota.c ---- .... MQTTDownloadThread----to mdownloadcallback(&minfo, ret)\n");
        mdownloadPkgCallback(&minfo, ret);
        HILOG_INFO(LOG_CORE, "mqtt_ota.c ---- .... MQTTDownloadThread----after mdownloadcallback(&minfo, ret)\n");
    //}
}

uint32_t DownloadFirmware(struct UpdateLiteInfo *info, char* url, downloadCallback callback)
{
    HILOG_INFO(LOG_CORE, "mqtt_ota.c ---- .... DownloadFirmware-------1\n");
    //HILOG_INFO(LOG_CORE, "mqtt_ota.c ----DownloadFirmware, payloadlen: %d, msgid: %d, message:\n %s\n", info->payloadlen, info->msgid, (char*)info->payload);
    mdownloadPkgCallback = callback;
    const char *firmwarefilename = "/userdata/upgrade/updater.zip";
    int ret = curlDownload(url, firmwarefilename, NULL);

    minfo.msgtype = 3;
    minfo.transType = 1;
    minfo.msgid = 0;
    minfo.payload = (uint8_t*)firmwarefilename;
    minfo.payloadlen = strlen(firmwarefilename);
    HILOG_INFO(LOG_CORE, "mqtt_ota.c ---- .... DownloadFirmware-------2\n");
    callback(&minfo, ret);
    // HILOG_INFO(LOG_CORE, "mqtt_ota.c ---- .... DownloadFirmware-------3\n");
    minfo.payload = NULL;
    minfo.payloadlen = 0;
    return 0;
}

uint32_t ReportUpdateResultInfo(struct UpdateLiteInfo *info)
{
    HILOG_INFO(LOG_CORE, "mqtt_ota.c ---- .... ReportUpdateResultInfo\n");

    return 0;
}

